//
//  common.swift
//  amap
//
//  Created by James Karl on 2019/9/14.
//

import Foundation
import MAMapKit
import AMapLocationKit

public struct LatLngData : Codable {
    public var latitude: Double = 0.0
    public var longitude: Double = 0.0
    public var name: String? = nil
    
    public init(json: [String: Any?]) {
        latitude = json["latitude"] as? Double ?? 0.0
        longitude = json["longitude"] as? Double ?? 0.0
        name = json["name"] as? String
    }
    
    public init(dict: NSDictionary) {
        latitude = dict["latitude"] as? Double ?? 0.0
        longitude = dict["longitude"] as? Double ?? 0.0
        name = dict["name"] as? String
    }
    
    public init(lat: Double = 0.0, lon: Double = 0.0, name: String? = nil) {
        self.latitude = lat
        self.longitude = lon
        self.name = name
    }
    
    func toMap() -> [String: Any?] {
        return ["latitude": latitude, "longitude": longitude , "name": name]
    }
}

struct ScreenPoint : Codable {
    var x: Int
    var y: Int
    
    func toMap() -> [String: Any?] {
        var m = [String: Any?]();
        m["x"]  = self.x
        m["y"] = self.y
        return m;
    }
}

struct LatLngBoundsData : Codable {
    var northeast: LatLngData = LatLngData()
    var southwest: LatLngData = LatLngData()
    
    init?(dict: NSDictionary) {
        if let ne = dict["northeast"] as? NSDictionary {
            self.northeast = LatLngData.init(dict: ne)
        } else {
            return nil
        }
        if let sw = dict["southwest"] as? NSDictionary {
            self.southwest = LatLngData.init(dict: sw)
        } else {
            return nil
        }
    }
    
    init(northeast: LatLngData, southwest: LatLngData) {
        self.northeast = northeast
        self.southwest = southwest
    }
    
    func toMap() -> [String: Any?] {
        var m = [String: Any?]()
        m["northeast"] = northeast.toMap()
        m["southwest"] = southwest.toMap()
        return m
    }
    
    func toCoordinateRegion() -> MACoordinateRegion {
        let center = CLLocationCoordinate2D(latitude: (northeast.latitude + southwest.latitude) / 2, longitude: (northeast.longitude + southwest.longitude)/2)
        let span = MACoordinateSpan(latitudeDelta: (northeast.latitude - southwest.latitude), longitudeDelta: (northeast.longitude - southwest.longitude))
        return MACoordinateRegion(center: center, span: span)
    }
    
    func contains(latLng: LatLngData) -> Bool{
        return latLng.longitude <= northeast.longitude
            && latLng.longitude >= southwest.longitude
            && latLng.latitude <= northeast.latitude
            && latLng.latitude >= southwest.latitude
    }
}

struct CameraPositionData : Codable {
    var bearing: Double?
    var target: LatLngData?
    var tilt: Double?
    var zoom: Double?
    var minZoom: Double?
    var maxZoom: Double?
    
    init(json: [String: Any?]) {
        bearing = json["bearing"] as? Double
        tilt = json["tilt"] as? Double
        zoom = json["zoom"] as? Double
        minZoom = json["minZoom"] as? Double
        maxZoom = json["maxZoom"] as? Double
        if let targetValue = json["target"] as? [String: Any?] {
            target = LatLngData(json: targetValue)
        }
    }
}


enum LogoPosition : Int {
    case bottomLeft
    case bottomCenter
    case bottomRight
}

enum ZoomPosition : Int {
    case rightCenter
    case rightBottom
}


struct UiSettings : Codable {
    var logoPosition: Int?
    var zoomPosition: Int?
    var compassEnabled: Bool?
    var gestureScaleByMapCenter: Bool?
    var indoorSwitchEnabled: Bool?
    var myLocationButtonEnabled: Bool?
    var rotateGesturesEnabled: Bool?
    var scaleControlsEnabled: Bool?
    var scrollGesturesEnabled: Bool?
    var tiltGesturesEnabled: Bool?
    var zoomControlsEnabled: Bool?
    var zoomGesturesEnabled: Bool?
    var allGesturesEnabled: Bool?
    
    init(json: [String: Any?]) {
        logoPosition = json["logoPosition"] as? Int
        zoomPosition = json["zoomPosition"] as? Int
        compassEnabled = json["compassEnabled"] as? Bool
        gestureScaleByMapCenter = json["gestureScaleByMapCenter"] as? Bool
        indoorSwitchEnabled = json["indoorSwitchEnabled"] as? Bool
        myLocationButtonEnabled = json["myLocationButtonEnabled"] as? Bool
        rotateGesturesEnabled = json["rotateGesturesEnabled"] as? Bool
        scaleControlsEnabled = json["scaleControlsEnabled"] as? Bool
        scrollGesturesEnabled = json["scrollGesturesEnabled"] as? Bool
        tiltGesturesEnabled = json["tiltGesturesEnabled"] as? Bool
        zoomControlsEnabled = json["zoomControlsEnabled"] as? Bool
        zoomGesturesEnabled = json["zoomGesturesEnabled"] as? Bool
        allGesturesEnabled = json["allGesturesEnabled"] as? Bool
    }
    
    var mapLogoPosition: LogoPosition? {
        get {
            if let v = logoPosition {
                return LogoPosition(rawValue: v)
            } else {
                return nil
            }
        }
    }
    
    var mapZoomPosition: ZoomPosition? {
        get {
            if let v = zoomPosition {
                return ZoomPosition(rawValue: v)
            } else {
                return nil
            }
        }
    }
    
}

struct MapCreationParams : Codable {
    let cameraPosition: CameraPositionData?
    let settings: UiSettings?
    
    
    init(json: [String: Any?]) {
        print("MapCreationParams.init", json)
        if let cameraPositionValue = json["cameraPosition"] as? [String: Any?] {
            cameraPosition = CameraPositionData(json: cameraPositionValue)
        } else {
            cameraPosition = nil
        }
        if let settingsValue = json["settings"] as? [String: Any?] {
            settings = UiSettings(json: settingsValue)
        } else {
            settings = nil
        }
    }
}


class MapLocation : Codable {
    var latitude: Double? = nil // 30.506518
    var longitude: Double? = nil // 114.379487
    var province: String? = nil // 湖北省
    var city: String? = nil // 武汉市
    var district: String? = nil // 洪山区
    var cityCode: String? = nil // 027
    var adCode: String? = nil // 420111
    var address: String? = nil // 湖北省武汉市洪山区虎泉街靠近中国邮政储蓄银行(吴家湾营业所)
    var country: String? = nil // 中国
    var road: String? = nil // 虎泉街
    var poiName: String? = nil // 中国邮政储蓄银行(吴家湾营业所)
    var street: String? = nil // 虎泉街
    var streetNum: String? = nil // =265号
    var aoiName: String? = nil // =五环天地
    var floor: String? = nil
    var errorCode: Int? = nil
    var errorInfo: String? = nil
    var locationType: Int? = nil
    
    init(location: MAUserLocation) {
        print("location: \(location)")
        self.latitude = location.location?.coordinate.latitude
        self.longitude = location.location?.coordinate.longitude
    }
    
    init(location: CLLocation?, regeocode: AMapLocationReGeocode?, error: Error?) {
        self.latitude = location?.coordinate.latitude
        self.longitude = location?.coordinate.longitude
        
        self.province = regeocode?.province
        self.city = regeocode?.city
        self.district = regeocode?.district
        self.cityCode = regeocode?.citycode
        self.adCode = regeocode?.adcode
        self.address = regeocode?.formattedAddress
        self.country = regeocode?.country
        self.street = regeocode?.street
        self.poiName = regeocode?.poiName
        self.aoiName = regeocode?.aoiName
        
        if let error = error as NSError? {
            self.errorInfo = error.localizedDescription
            self.errorCode = error.code
            print("get MapLocation error: \(error)")
        }
        //        self.floor = regeocode?.
        //        self.road = regeocode?.
        //        self.locationType = regeocode?
        
    }
    
    func toMap() -> [String: Any?] {
        return [
            "latitude": latitude,
            "longitude": longitude,
            "province": province,
            "city": city,
            "district": district,
            "cityCode": cityCode,
            "adCode": adCode,
            "address": address,
            "country": country,
            "road": road,
            "poiName": poiName,
            "street": street,
            "streetNum": streetNum,
            "aoiName": aoiName,
            "floor": floor,
            "errorCode": errorCode,
            "errorInfo": errorInfo,
            "locationType": locationType,
        ]
    }
}
